package fr.umlv.galcon.planet;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.Map;

import fr.umlv.galcon.game.GalconManager;
import fr.umlv.galcon.item.GraphicItem;
import fr.umlv.galcon.item.ItemListSingleton;
import fr.umlv.galcon.player.Player;
import fr.umlv.galcon.ship.ShipProperties;
import fr.umlv.galcon.utils.Utils;

public class Planet implements GraphicItem {
    private final Point2D center;
    private final int size;
    private Player owner;
    private ShipProperties shipProperties;
    private final Ellipse2D areaShape;
    private int nbShips;
    private int productionrate;
    private final StockManager stock;
    private final SelectorManager selectorManager;

    /**
     * Planet's constructor
     * 
     * @param x
     *            : position X of the planet
     * @param y
     *            : position Y of the planet
     * @param size
     *            : size of the planet
     * @param owner
     *            : owner of the planet
     * @param shipProperties
     *            : type of ship for the planet
     * @param nbShips
     *            : nb ship at the creation of the planet
     * @param productionRate
     *            : the production rate of the planet
     */
    public Planet(int x, int y, int size, Player owner, ShipProperties shipProperties, int nbShips, int productionRate) {
	this.center = new Point2D.Double(x, y);
	this.size = size;
	this.owner = owner;
	this.shipProperties = shipProperties;
	this.nbShips = nbShips;
	this.productionrate = productionRate;
	this.areaShape = new Ellipse2D.Double(x - size / 2 - 8, y - size / 2 - 8, size + 16, size + 16);
	this.stock = new StockManager(this, this.productionrate, this.nbShips, this.nbShips);
	this.selectorManager = new SelectorManager(this);
    }

    /**
     * Get the Planet's owner
     * 
     * @return the owner
     */
    public Player getOwner() {
	return owner;
    }

    /**
     * Get the StockManager of the planet
     * 
     * @return the StockManager
     */
    public StockManager getStock() {
	return stock;
    }

    /**
     * Set the Planet's owner
     * 
     * @param owner
     */
    public void setOwner(Player owner) {
	this.owner = owner;
    }

    /**
     * Get the Planet's ship type
     * 
     * @return ship type
     */
    public ShipProperties getShipProperties() {
	return shipProperties;
    }

    /**
     * Set the Planet's ship type
     * 
     * @param shipProperties
     */
    public void setShipProperties(ShipProperties shipProperties) {
	this.shipProperties = shipProperties;
    }

    /**
     * Get the Planet's center
     * 
     * @return the center
     */
    public Point2D getCenter() {
	return this.center;
    }

    /**
     * Get the Planet's size
     * 
     * @return size
     */
    public int getSize() {
	return size;
    }

    /**
     * Get nb Planet's ships
     * 
     * @return nb ships
     */
    public int getNbShips() {
	return nbShips;
    }

    /**
     * Set the Planet's nb sips
     * 
     * @param nbShips
     */
    public void setNbShips(int nbShips) {
	this.nbShips = nbShips;
    }

    /**
     * Get the Planet's production rate
     * 
     * @return production rate
     */
    public int getProductionrate() {
	return productionrate;
    }

    /**
     * Set the Planet's production rate
     * 
     * @param productionrate
     */
    public void setProductionrate(int productionrate) {
	this.productionrate = productionrate;
    }

    /**
     * Get the Planet's area shape
     * 
     * @return area of the planet
     */
    public Ellipse2D getAreaShape() {
	return areaShape;
    }

    /**
     * Get the Planet's SelectorManager
     * 
     * @return SelectorManager
     */
    public SelectorManager getSelectorManager() {
	return selectorManager;
    }

    /**
     * The Planet is conquered by an other Player.
     * 
     * @param player
     *            The Player who will own the Planet.
     * @param shipProperties
     *            Ship properties of the Ship production.
     */
    public void conquire(Player player, ShipProperties shipProperties) {
	Map<Player, Integer> map = GalconManager.getPlayers();

	if (map.containsKey(this.owner))
	    map.put(this.owner, map.get(this.owner) - 1);
	if (map.containsKey(player))
	    map.put(player, map.get(player) + 1);

	this.owner = player;
	if (shipProperties.getPower() > this.shipProperties.getPower())
	    this.shipProperties = shipProperties;
	this.stock.setRealStock(0);
	this.stock.setShipStock(0);
	this.selectorManager.setSelected(false);
	if (ItemListSingleton.getInstance().getClickedPlanetList().contains(this))
	    ItemListSingleton.getInstance().getClickedPlanetList().remove(this);
    }

    @Override
    public void draw(Graphics2D graphics) {
	if (!GalconManager.isOver()) {
	    double currentX = getCenter().getX();
	    double currentY = getCenter().getY();
	    int width = getSize();

	    graphics.setColor(Utils.getPlayerColor(owner.getId()));

	    // Draw the planet
	    graphics.drawOval((int) currentX - width / 2, (int) currentY - width / 2, width, width);
	    graphics.fillOval((int) currentX - width / 2, (int) currentY - width / 2, width, width);

	    // A faire si la plan�te est sélectionnée
	    if (getSelectorManager().isSelected()) {
		graphics.setColor(Color.orange);
		graphics.setStroke(new BasicStroke(1.5f));
		graphics.draw(this.areaShape);
		graphics.setStroke(new BasicStroke(1f));
	    }

	    // Display the planet's ships stock
	    this.stock.displayStock(graphics);
	}
	getSelectorManager().areaSelection(graphics);

    }

    @Override
    public boolean intersect(GraphicItem item) {
	if (item.getShape().intersects(getShape().getBounds2D())) {
	    return true;
	}
	return false;
    }

    @Override
    public Shape getShape() {
	return areaShape;
    }

    /**
	 * 
	 */
    @Override
    public boolean contains(Point2D p) {
	return areaShape.contains(p);
    }

}
